package com.dongdongshop.controller;

import ch.qos.logback.core.encoder.EchoEncoder;
import com.alibaba.dubbo.config.annotation.Reference;
import com.dongdongshop.config.SmsConstant;
import com.dongdongshop.data.Result;
import com.dongdongshop.data.ResultEnum;
import com.dongdongshop.pojo.user.TbUser;
import com.dongdongshop.service.user.UserService;
import com.dongdongshop.shiro.ShiroUtils;
import com.dongdongshop.utils.HttpClientUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("user")
public class UserController {

    private final Logger logger= LoggerFactory.getLogger(UserController.class);

    @Reference
    private UserService userService;
    @Resource
    private RocketMQTemplate rocketMQTemplate;
    @Resource
    private RedisTemplate redisTemplate;

    @RequestMapping("toLogin")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("index")
    public String index(){
        return "index";
    }

    @RequestMapping("toRegister")
    public String toRegister(){
        return "register";
    }

    //登录
    @RequestMapping("login")
    public String login(String username, String password, Model model){
        //使用shiro登录，获取subject
        Subject subject = SecurityUtils.getSubject();
        //将参数封装到token
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            //登录成功
            subject.login(token);
        }catch (UnknownAccountException e){
            model.addAttribute("message","用户不存在");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("message","密码不正确");
            return "login";
        }
        //跳转页面
        return "index";
    }

    //注册
    @RequestMapping("addUser")
    @ResponseBody
    public Result addUser(TbUser user,String code){
       // System.out.println("11111111");
        try {
            if (StringUtils.isBlank(user.getUsername())){
                return Result.response(ResultEnum.FAIL).setData("用户名不能为空");
            }
            if(StringUtils.isBlank(user.getPassword())) {
                return Result.response(ResultEnum.FAIL).setData("密码不能为空");
            }
            if(StringUtils.isBlank(user.getPhone())) {
                return Result.response(ResultEnum.FAIL).setData("手机号不能为空");
            }
            //从redis中取出key
            String code1=(String)redisTemplate.opsForHash().get(SmsConstant.PHONENUMBER,user.getPhone());
           if (!code1.equals(code)){
               return Result.response(ResultEnum.FAIL).setData("验证码不一样");
           }
            String salt = ShiroUtils.generateSalt(6);
            System.out.println("盐" + salt.toString());
            String md5 = ShiroUtils.encryptPassword("MD5", user.getPassword(), salt, 3);
            System.out.println("密文 " + md5.toString());
            user.setSalt(salt);
            user.setPassword(md5);
            user.setCreated(new Date());
            user.setUpdated(new Date());

            //判断用户存在不存在
            List<TbUser> tbUser =userService.getByName(user.getUsername());
            if (tbUser.size()==1){
                return Result.response(ResultEnum.FAIL).setData("用户已存在");
            }
            int i=userService.addUserAll(user);
            if (i>0){
                return Result.response(ResultEnum.OK).setData("注册成功");
            }else {
                return Result.response(ResultEnum.FAIL).setData("注册失败");
            }

            /* //获取验证码进行判断
            Boolean b=userService.phoneByCode(user.getPhone(),code);
            if (b == false){
                return Result.response(ResultEnum.FAIL).setData("验证码错误");
            }*/
        }catch (Exception e){
            logger.info("系统错误",e);
            return Result.response(ResultEnum.FAIL);
        }
    }

    //发送验证码  使用SDK方法
    @RequestMapping("sendCode")
    @ResponseBody
    public Result sendCode(String phone){
        try {
            //验证码随机数
            String code= RandomStringUtils.randomNumeric(4);
            //将手机号和验证码发送mq
            String phoneCode=""+phone+","+code+"";
            //发送主题信息 convertAndSend()可以指定topic 没有就创建topic，也可以send（这个只是在有topic前提下）
            rocketMQTemplate.convertAndSend("sms_code",phoneCode);
            //将code保存到redis中
            HashOperations opsForHash = redisTemplate.opsForHash();
            opsForHash.put(SmsConstant.PHONENUMBER,phone,code);
            //超时时间
            redisTemplate.expire(SmsConstant.PHONENUMBER,1, TimeUnit.HOURS);
            logger.info("发送成功");
            return Result.response(ResultEnum.OK);
        }catch (Exception e){
            logger.info("系统错误",e);
            return Result.response(ResultEnum.FAIL);
        }
    }

    //发送验证码 使用API
    @RequestMapping("sendClient")
    @ResponseBody
    public Result sendAPI(String phone){
        try {
            //验证码随机数
            String code= RandomStringUtils.randomNumeric(4);
            //将code保存到redis中
            HashOperations opsForHash = redisTemplate.opsForHash();
            opsForHash.put(SmsConstant.PHONENUMBER,phone,code);
            //超时时间
            redisTemplate.expire(SmsConstant.PHONENUMBER,1, TimeUnit.HOURS);
            signMessage(phone,code);
            logger.info("发送成功");
            return Result.response(ResultEnum.OK);
        }catch (Exception e){
            logger.info("系统错误",e);
            return Result.response(ResultEnum.FAIL);
        }
    }
   //在阿里云API参考 请求签名里得示例 地址https://help.aliyun.com/document_detail/101343.html?spm=a2c4g.11186623.6.618.1e7d6ed1aYteCw
    public void signMessage(String phoneNum,String code) throws Exception {
        String accessKeyId = "LTAI4GGVDj2itAnhTMPvRc1L";
        String accessSecret = "C8LyU35VquqHEdAUPIQv0xKxtrczoU";
        java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
        java.util.Map<String, String> paras = new java.util.HashMap<String, String>();
        // 1. 系统参数
        paras.put("SignatureMethod", "HMAC-SHA1");
        paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());
        paras.put("AccessKeyId", accessKeyId);
        paras.put("SignatureVersion", "1.0");
        paras.put("Timestamp", df.format(new java.util.Date()));
        paras.put("Format", "XML");
        // 2. 业务API参数  对应SmsServiceImpl里得信息
        paras.put("Action", "SendSms");
        paras.put("Version", "2017-05-25");
        paras.put("RegionId", "cn-hangzhou");
        paras.put("PhoneNumbers", phoneNum);
        paras.put("SignName", "顺顺通1号");
        paras.put("TemplateParam", "{\"sms_code\":"+code+"}");//
        paras.put("TemplateCode", "SMS_194026835");
//        paras.put("OutId", "123");
        // 3. 去除签名关键字Key
        if (paras.containsKey("Signature"))
            paras.remove("Signature");
        // 4. 参数KEY排序
        java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
        sortParas.putAll(paras);
        // 5. 构造待签名的字符串
        java.util.Iterator<String> it = sortParas.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (it.hasNext()) {
            String key = it.next();
            sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
        }
        String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append("GET").append("&");
        stringToSign.append(specialUrlEncode("/")).append("&");
        stringToSign.append(specialUrlEncode(sortedQueryString));
        String sign = sign(accessSecret + "&", stringToSign.toString());
        // 6. 签名最后也要做特殊URL编码
        String signature = specialUrlEncode(sign);
        System.out.println(paras.get("SignatureNonce"));
        System.out.println("\r\n=========\r\n");
        System.out.println(paras.get("Timestamp"));
        System.out.println("\r\n=========\r\n");
        System.out.println(sortedQueryString);
        System.out.println("\r\n=========\r\n");
        System.out.println(stringToSign.toString());
        System.out.println("\r\n=========\r\n");
        System.out.println(sign);
        System.out.println("\r\n=========\r\n");
        System.out.println(signature);
        System.out.println("\r\n=========\r\n");
        // 最终打印出合法GET请求的URL
        System.out.println("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);
        HttpClientUtil.doGet("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);

    }

    public static String specialUrlEncode(String value) throws Exception {
        return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }
    public static String sign(String accessSecret, String stringToSign) throws Exception {
        javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }
}
